/*****************************************************************************
 *  Entropy - Emerging Network To Reduce Orwellian Potency Yield
 *
 *  Copyright (C) 2005 Juergen Buchmueller <pullmoll@t-online.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 *	$Id: bignum.h,v 1.7 2006/02/21 16:14:26 pullmoll Exp $
 *****************************************************************************/
#ifndef _bignum_h_
#define _bignum_h_

#include "osd.h"
#include "tools.h"

#ifndef	O_BINARY
#define	O_BINARY 0
#endif

#ifndef	HAVE_U64
#define	HAVE_U64 1
#endif

/* set to number of bits of RSA keys */
#ifndef	RSABITS
#define	RSABITS	2048
#endif

/* up to 512 limbs (512 * 32 = 16384 bits) numbers */
#define	BN_MAXSIZE 512
#define	LIMBBITS 32
#define	LIMBMASK 0xfffffffful
#define	HALFMASK 0x0000fffful
#define	DIGMSB 0x80000000ul
#define	DIGLSB 0x00000001ul

/* number of limbs in RSA keys */
#define	RSALIMBS (RSABITS/LIMBBITS)

/*
 * @brief Minimum number of limbs for a RSA prime
 *
 * For a RSABITS value of 2048, we allow the first prime
 * to have between 682 bits and 1024 bits, the other prime
 * between 1024 and 1366 bits.
 *
 */
#define	RSALIMBS_MIN (RSABITS/3/LIMBBITS)
#define	RSALIMBS_MAX (RSABITS/2/LIMBBITS)

typedef uint32_t cnt_t;
typedef uint16_t half_t;
typedef uint32_t limb_t;
#if HAVE_U64
typedef uint64_t dlimb_t;
#endif

/* less significant half limb */
#define	LSH(d)	((half_t)(d))
/* more significant half limb */
#define	MSH(d)	((limb_t)(d)>>16)
/* shift left half limb */
#define	SHL(d)	((limb_t)(d)<<16)

/* single limb functions */
limb_t sl_div(limb_t *q, limb_t *r, limb_t u[2], limb_t v);
limb_t sl_gcd(limb_t x, limb_t y);
int sl_isprime(limb_t w, cnt_t t);
int sl_modexp(limb_t *exp, limb_t x, limb_t n, limb_t d);
int sl_modinv(limb_t *inv, limb_t u, limb_t v);
int sl_modmul(limb_t *a, limb_t x, limb_t y, limb_t m);
int sl_mul(limb_t p[2], limb_t x, limb_t y);
limb_t sl_random(limb_t lower, limb_t upper);

/* big number functions (max. MAXSIZE limbs) */
void bn_zero(limb_t a[], cnt_t nlimb);
void bn_limb(limb_t a[], limb_t d, cnt_t nlimb);
void bn_copy(limb_t a[], limb_t b[], cnt_t nlimb);
cnt_t bn_sizeof(limb_t a[], cnt_t nlimb);
int bn_cmp_limb(limb_t a[], limb_t b, cnt_t nlimb);
int bn_cmp(limb_t a[], limb_t b[], cnt_t nlimb);

/* big number to hex, decimal, binary */
const char *bn2x(limb_t a[], cnt_t nlimb);
const char *bn2d(limb_t a[], cnt_t nlimb);
const char *bn2f(limb_t a[], cnt_t alimb, limb_t b[], cnt_t blimb);
const char *bn2b(limb_t a[], cnt_t nlimb);

/* big number with single limb operations */
limb_t bn_add_limb(limb_t w[], limb_t u[], limb_t v, cnt_t nlimb);
limb_t bn_sub_limb(limb_t w[], limb_t u[], limb_t v, cnt_t nlimb);
limb_t bn_div_limb(limb_t q[], limb_t u[], limb_t v, cnt_t nlimb);
limb_t bn_mod_limb(limb_t u[], limb_t d, cnt_t nlimb);
limb_t bn_mul_limb(limb_t w[], limb_t u[], limb_t v, cnt_t nlimb);

/* big number with single limb <= HALFMASK operations */
limb_t bn_div_half(limb_t q[], limb_t u[], limb_t v, cnt_t nlimb);
limb_t bn_mod_half(limb_t a[], limb_t d, cnt_t nlimb);

/* big number operations */
limb_t bn_add(limb_t w[], limb_t u[], limb_t v[], cnt_t nlimb);
limb_t bn_sub(limb_t w[], limb_t u[], limb_t v[], cnt_t nlimb);
limb_t bn_shl(limb_t a[], limb_t b[], cnt_t x, cnt_t nlimb);
limb_t bn_shr(limb_t a[], limb_t b[], cnt_t x, cnt_t nlimb);
int bn_mul(limb_t w[], limb_t u[], limb_t v[], cnt_t nlimb);
int bn_div(limb_t q[], limb_t r[], limb_t u[], limb_t v[], cnt_t ulimb, cnt_t vlimb);
limb_t bn_mod(limb_t r[], limb_t u[], cnt_t ulimb, limb_t v[], cnt_t vlimb);
int bn_gcd(limb_t g[], limb_t x[], limb_t y[], cnt_t nlimb);
int bn_sqrt(limb_t g[], limb_t x[], limb_t y[], cnt_t rlimb, cnt_t nlimb);
int bn_modexp(limb_t y[], limb_t x[], limb_t e[], limb_t m[], cnt_t nlimb);
int bn_modinv(limb_t inv[], limb_t u[], limb_t v[], cnt_t nlimb);
limb_t bn_modmul(limb_t a[], limb_t x[], limb_t y[], limb_t m[], cnt_t nlimb);
int bn_isprime(limb_t w[], cnt_t nlimb, cnt_t t);

/* RSA operations */
int rsa_setup(void);
int rsa_init(void **rsa);
int rsa_get_public_key(void *rsa, void *pubkey, int size);
int rsa_set_public_key(void *rsa, void *pubkey, int size);
int rsa_strip(void *rsa, void *plaintext, int size);
int rsa_decode(void *rsa, void *plaintext, void *ciphertext, int size);
int rsa_encode(void *rsa, void *ciphertext, void *plaintext, int size);
int rsa_destroy(void **rsa);

#endif	/* !defined(_bignum_h_) */
